package com.polaris.live.ui.main.live

import android.os.Bundle
import androidx.annotation.CallSuper
import androidx.lifecycle.MutableLiveData
import androidx.recyclerview.widget.RecyclerView
import androidx.viewbinding.ViewBinding
import com.polaris.live.adapter.home.HomeManAdapter
import com.polaris.live.common.adapter.BaseAdapter
import com.polaris.live.common.cacha.CacheUtil
import com.polaris.live.common.mvvm.viewmodel.BaseViewModel
import com.polaris.live.common.network.state.ResultState
import com.polaris.live.manager.UserStateManager
import com.polaris.live.resp.back_resp.DisplayUserBean
import com.polaris.live.resp.back_resp.copyState
import com.polaris.live.resp.base.ListResp
import com.polaris.live.ui.main.fragment.AbstractBannerPromptFragment
import com.polaris.live.utils.interfaces.OnAutoRefreshListener
import com.polaris.live.utils.state.getDisplayPosition
import com.polaris.live.widget.refresh.OnListListener
import com.polaris.live.widget.refresh.RefreshRecyclerView

/**
 * AbstractLiveListFragment
 *
 * @author Created by 半仙 on 2024/2/27/027 15:15
 */
abstract class AbstractLiveListFragment<VM, VB> : AbstractBannerPromptFragment<VM, VB>(),
    OnAutoRefreshListener where VB : ViewBinding, VM : BaseViewModel, VM : OnListListener {
    private var lastRefreshTime: Long? = null

    //是隔多久回到页面刷新一次
    private var refreshTime = ONE_MINUTES

    @CallSuper
    override fun initView(savedInstanceState: Bundle?) {
        super.initView(savedInstanceState)

        mAdapter.setGridSpanSizeLookup { gridLayoutManager, viewType, _ ->
            if (viewType == HomeManAdapter.TYPE_NORMAL) {
                1
            } else {
                gridLayoutManager.spanCount
            }
        }
        refreshView.apply {
            recycler.layoutManager = layoutManager
            attachedAdapter(mAdapter, mViewModel).observeFilter(
                this@AbstractLiveListFragment,
                listLiveData,
                { src, dest ->
                    val srcId = if (src is DisplayUserBean) {
                        src.base.userId
                    } else {
                        Long.MAX_VALUE / 2 + src.hashCode()
                    }
                    val destId = if (dest is DisplayUserBean) {
                        dest.base.userId
                    } else {
                        Long.MAX_VALUE / 2 + dest.hashCode()
                    }

                    srcId.compareTo(destId)
                }) {
                if (this == 0) {
                    lastRefreshTime = CacheUtil.getServerTime()
                }
            }
        }
        initListener()
        refreshView.recycler.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                super.onScrollStateChanged(recyclerView, newState)
                if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                    updateUserStateObserve()
                }
            }
        })

        UserStateManager.observe(this, {
            getDisplayUserIds()
        }, { messages ->
            val indices = refreshView.recycler.getDisplayPosition(mAdapter.data)?.indices
                ?: mAdapter.data.indices

            messages.forEach { message ->
                for (i in indices) {
                    val item = mAdapter.getItem(i)
                    if (item is DisplayUserBean && item.base.userId == message.state.userId) {
                        mAdapter.setData(i, item.copyState(message))
                        break
                    }
                }
            }
        })
    }

    private fun updateUserStateObserve(userIds: List<Long> = getDisplayUserIds()) {
        UserStateManager.updateUserObserve(this, userIds)
    }

    override fun initData() {
        super.initData()
        requireView().post { refreshView.autoRefresh() }
    }

    override fun onAutoRefresh() {
        if (!isCreated() || !isLoadData()) {
            return
        }

        refreshView.recycler.scrollToPosition(0)
        refreshView.autoRefresh()
    }

    override fun onResume() {
        toRefresh()

        super.onResume()
    }

    override fun onHiddenChanged(hidden: Boolean) {
        super.onHiddenChanged(hidden)

        if (!hidden) {
            toRefresh()
        }
    }

    private fun toRefresh() {
        if (isLoadData()) {
            val lastRefreshTime = lastRefreshTime
            if (lastRefreshTime == null || CacheUtil.getServerTime() - lastRefreshTime > 60 * refreshTime) {
                onAutoRefresh()
            }
        }
    }

    abstract fun initListener()

    abstract val refreshView: RefreshRecyclerView

    abstract val layoutManager: RecyclerView.LayoutManager

    abstract val mAdapter: BaseAdapter<Any, *>

    abstract val listLiveData: MutableLiveData<ResultState<ListResp<Any>>>

    private fun getDisplayUserIds(): List<Long> {
        val wrapper = refreshView.recycler.getDisplayPosition(mAdapter.data)
            ?: return emptyList()

        return mAdapter.data.subList(wrapper.firstPosition, wrapper.lastPosition).mapNotNull {
            if (it is DisplayUserBean) {
                it.base.userId
            } else {
                null
            }
        }
    }

    fun setRefreshTime(time: Int) {
        refreshTime = time
    }

    companion object {
        const val FIVE_MINUTES = 5000
        const val ONE_MINUTES = 1000
    }
}